{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# クラス定義\n",
    "\n",
    "* クラス名\n",
    "    * 大文字ではじめる\n",
    "        * 小文字ではじめると構文エラーになる\n",
    "        * <font color=\"red\">クラス名は定数</font>だから\n",
    "    * Rubyインタプリタのクラス定義の挙動\n",
    "        * 指定されたクラス名で定数を作成する\n",
    "        * この定数に定義されたクラスを格納する\n",
    "* インスタンスメソッド\n",
    "    * defで定義\n",
    "        * 例はFooクラスにインスタンスメソッドmethod1を定義している\n",
    "        * initializeという名前のメソッドは特別なメソッド\n",
    "            * 初期化のときに実行されるメソッド\n",
    "            * 例は引数aを受け取る初期化メソッドを定義している\n",
    "* インスタンス変数\n",
    "    * 頭に「@」がついている変数はインスタンス変数になる\n",
    "* インスタンス捜査\n",
    "    * 作成したクラスオブジェクトに対してnewメソッドを実行することでインスタンスを生成できる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "### クラスを定義(クラスオブジェクトの作成)\n",
    "class Foo\n",
    "  ### セッター\n",
    "  def initialize(a)\n",
    "    @a = a\n",
    "  end\n",
    "  \n",
    "  ### ゲッター\n",
    "  def method1\n",
    "    @a\n",
    "  end\n",
    "end\n",
    "\n",
    "### クラスオブジェクトにnewメソッドを実行してインスタンスを生成\n",
    "### newメソッドに渡した引数は異なる\n",
    "foo1 = Foo.new(1)\n",
    "foo2 = Foo.new(2)\n",
    "\n",
    "### 定義したインスタンスメソッドを実行\n",
    "puts foo1.method1\n",
    "puts foo2.method1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## Rubyにおいてクラスはオブジェクト\n",
    "\n",
    "* メソッドの実行や変数への再代入が可能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "class Foo2\n",
    "  def initialize(a)\n",
    "    @a = a\n",
    "  end\n",
    "  \n",
    "  def method1\n",
    "    @a\n",
    "  end\n",
    "end\n",
    "\n",
    "### Foo2の参照先を変数aに代入\n",
    "a = Foo2\n",
    "\n",
    "### Fooと同じように操作できる\n",
    "foo3 = a.new(3)\n",
    "puts foo3.method1\n",
    "puts a.new(4).method1\n",
    "\n",
    "### 定数なので警告が出るが、代入して上書き可能\n",
    "#Foo = 1\n",
    "#puts Foo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## class式の評価順序\n",
    "\n",
    "* class式が評価されるとクラス定義の内部が評価される\n",
    "    * Rubyのクラス定義は内部がスキップされることなく順に評価される"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "実行すると1から順に評価される\n",
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "puts \"実行すると1から順に評価される\"\n",
    "puts 1\n",
    "class Hoge\n",
    "  puts 2\n",
    "end\n",
    "puts 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## classメソッド\n",
    "\n",
    "* インスタンスから生成元のクラスオブジェクトを参照する\n",
    "    * foo1が指すオブジェクトはFooクラスのインスタンス\n",
    "        * foo1.classはFooが返る"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Foo\n",
      "true\n"
     ]
    }
   ],
   "source": [
    "class Foo\n",
    "  def initialize(a)\n",
    "    @a = a\n",
    "  end\n",
    "  \n",
    "  def method1\n",
    "    @a\n",
    "  end\n",
    "end\n",
    "\n",
    "foo1 = Foo.new(1)\n",
    "\n",
    "puts foo1.class\n",
    "puts foo1.class == Foo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# クラス継承\n",
    "\n",
    "* Fooクラスを継承したFooExtクラスを定義\n",
    "    * FooExtのインスタンスを生成\n",
    "        * 第一引数3はsuperメソッドの引数に入る\n",
    "            * 引数はsuperclassであるFooクラスの<font color=\"red\">同名のメソッドにそのまま</font>渡される\n",
    "        * 第二引数4はインスタンス変数bに代入される\n",
    "        * method2の引数5はcに代入される\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "12\n",
      "Foo\n"
     ]
    }
   ],
   "source": [
    "class Foo\n",
    "  def initialize(a)\n",
    "    @a = a\n",
    "  end\n",
    "  \n",
    "  def method1\n",
    "    @a\n",
    "  end\n",
    "end\n",
    "\n",
    "class FooExt < Foo\n",
    "  def initialize(a,b)\n",
    "    @b = b\n",
    "    super a\n",
    "  end\n",
    "  \n",
    "  def method2(c)\n",
    "    @a + @b + c\n",
    "  end\n",
    "end\n",
    "\n",
    "fooExt = FooExt.new(3, 4)\n",
    "puts fooExt.method1\n",
    "puts fooExt.method2(5)  \n",
    "\n",
    "### スーパークラスの取得\n",
    "puts FooExt.superclass"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.3.1",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
